跳到主要内容

Git 提交相关

Git 的结构

  • 本地库:历史版本
  • 暂存区:打算提交,但是还没提交的地方
  • 工作区
graph LR 工作区 --git add--> 暂存区 暂存区 --git commit--> 本地库

提交相关

Git Commit

Git 把数据看作是小型文件系统的一组快照。每次提交更新时 Git 都会对当前的全部文件制作一个快照,并保存这个 快照 的索引。

为了高效,如果文件没有修改,Git 不再重新储存该文件,而是只保留一个链接指向之前存储的文件。所以 Git 的工作方式可以称之为快照流

Git 还保存了提交的历史记录。这也是为什么大多数提交记录的上面都有父节点的原因

# 提交命令
git commit filename

提交命令具体使用

git add # 把工作区代码提交到缓存区
git rm --cached filename # 把文件从缓存区删除(不是删掉工作区的文件)

git commit filename # 提交缓存区的文件本地库(提交后自动进入vim请你输入提交的修改信息,类似注释)

注意:对于仓库中没有的文件,git commit file 不能提交,所以当库里不存在那个文件时,必须先 add ,当库里已经有那个文件之后 修改文件可以不 add 直接 commit

git commit -m "这里是注释" filename

注意:如果不加 -m 参数,会进入 vim 编辑器

如果是直接提交(省略add这步)则用 git commit -a,但是就无法撤销了。

git restore filename 撤销修改(注意旧版用的是git checkout

如果要提交全部文件,则直接用 . 代替就行了

git add .
git commit -m"注释" .

追加提交

如果我们不小心提交了一版我们不满意的代码,并且给它推送到服务器了,在代码没被 merge 之前我们希望再修改一版满意的,而如果我们不想在服务器上 abondon,那么我们怎么做呢?

git commit --amend

这个 amend 参数也叫追加提交,它可以在不增加一个新的 commit-id 的情况下将新修改的代码追加到前一次的 commit-id 中

假如现在版本库里最近的一版正是我们想要追加进去的那版(就是处于当前最新的版本),此时是最简单的,直接修改工作区代码,然后 git add,之后就可以直接进行 git push 到服务器,中间不需要进行其他的操作如 git pull

如果现在版本库里最近的一版不是我们想要追加进去的那版,那么此时我们需要将版本库里的版本回退到我们想要追加的那一版,想要将版本回退到我们想要的哪一版可以使用 gitk 或其他的图形界面化工具。

在终端输入 gitk,回车,会弹出 gitk 的图形界面,在界面的左侧部分陈列着版本库中的一条条 commit-id,此时选中我们需要的那一版,右键点击之后会弹出一个 选择菜单,如果是在 master 分支上,那么其中会有一项是 Reset master branch to here,点击这项,会弹出一个名为 confirm reset 的确认 box,选择 reset type 中的 hard 项,再点击 OK

关闭gitk图形界面,回到终端,运行 git log -1 命令,发现现在版本库里最近的一次提交已经是我们希望的那一版了,此时再在工作区直接修改代码,改完之后进行 git add,再执行本 git commit --amend 命令,之后 git push

再使用命令打印一下它们的图状关系

git log --graph --decorate --oneline --simplify-by-decoration --all

当然,上面的操作可以使用命令来实现,如下所示:

如果我们不知道我们需要的版本与现在最近的版本中间隔着 n 个提交,那么我们可以使用 git log 来查看版本库中的 commit-id,找到我们需要的 commit-id 后,在终端中执行

git reset --hard commit-id

这个命令执行完后,运行 git log -1 命令我们会发现现在版本库里最近的一版就是我们需要的那版,此时再在工作区直接修改代码,改完之后进行 git add 再执行本 git commit --amend 命令,之后 git push

Git Tags 添加锚点

Tags 它们可以永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。(在某种程度上的永久 —— 因为标签可以被删除后可以重新在另外一个位置创建同名的标签)

更难得的是,它们并不会随着新的提交而移动。你也不能到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。

咱们来看看标签到底是什么样。

Git示范:

咱们先建立一个标签,指向提交记录 C1,表示这是我们 1.0 版本。

git tag v1 c1

我们将这个标签命名为 v1,并且明确地让它指向提交记录 C1,如果你不指定提交记录,Git 会用 HEAD 所指向的位置。

Git Describe 找到最近的锚点

由于标签在代码库中起着 “锚点” 的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe

Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用 git bisect(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。

git describe 的​​语法是:

git describe <ref>

<ref> 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会以你目前所 checkout 的位置(HEAD)。

它输出的结果是这样的:

<tag>_<numCommits>_g<hash>

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录,hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。

当 ref 提交记录上有某个标签时,则只输出标签名称

如下例子所示:

git  tag v2 c3

然后执行下面的命令

git describe master 
# 会输出:v1_2_gC2

git describe side
# 会输出:v2_1_gC4

隐藏 Stash 操作

假设您正在为产品新的功能编写/实现代码,当正在编写代码时,突然出现软件客户端升级。这时,您必须将新编写的功能代码保留几个小时然后去处理升级的问题。在这段时间内不能提交代码,也不能丢弃您的代码更改。 所以需要一些临时等待一段时间,您可以存储部分更改,然后再提交它。

在 Git 中,隐藏操作将使您能够修改跟踪文件,阶段更改,并将其保存在一系列未完成的更改中,并可以随时重新应用。

现在,要切换分支以进行客户升级,但不想提交一直在做的工作; 那么可以把当前工作的改变隐藏起来。 要将一个新的存根推到堆栈上,运行 git stash 命令。

$ git stash

现在,工作目录是干净的,所有更改都保存在堆栈中。 现在使用 git status 命令来查看当前工作区状态。

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

现在,可以安全地切换分支并在其他地方工作。通过使用 git stash list 命令来查看已存在更改的列表。

$ git stash list
stash@{0}: WIP on master: ef07ab5 synchronized with the remote repository

假设您已经解决了客户升级问题,想要重新开始新的功能的代码编写,查找上次没有写完成的代码,只需执行 git stash pop 命令即可从堆栈中删除更改并将其放置在当前工作目录中。